package com.qing.utils.spel;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.List;
import java.util.stream.Collectors;

public class SpELMain {

    private static final String USER = "{\n" +
            "    \"name\": \"zhangsan\",\n" +
            "    \"userId\": \"1\",\n" +
            "    \"userGroup\": \"g1\",\n" +
            "    \"org\": \"o1\",\n" +
            "    \"location\": \"1\",\n" +
            "    \"belongType\": \"1\",\n" +
            "    \"isSimShield\": \"0\"\n" +
            "  }";

    private static final String STRATEGY = "[\n" +
            "  {\n" +
            "    \"name\": \"策略1\",\n" +
            "    \"id\": \"ID1\",\n" +
            "    \"conditions\": [\n" +
            "      {\n" +
            "        \"name\": \"userId\",\n" +
            "        \"value\": \"1,2,3\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"(#userId=='1') or (#userId=='2')or (#userId=='3')\"\n" +
            "      },\n" +
            "      {\n" +
            "        \"name\": \"belongType\",\n" +
            "        \"value\": \"1\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"#belongType=='1'\"\n" +
            "      },\n" +
            "      {\n" +
            "        \"name\": \"location\",\n" +
            "        \"value\": \"1,2,3\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"#location=='1' or #location=='2' or #location=='3'\"\n" +
            "      }\n" +
            "    ]\n" +
            "  },\n" +
            "  {\n" +
            "    \"name\": \"策略2\",\n" +
            "    \"id\": \"ID2\",\n" +
            "    \"conditions\": [\n" +
            "      {\n" +
            "        \"name\": \"userId\",\n" +
            "        \"value\": \"2,3\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"#userId=='1' or #userId=='2' or #userId=='3' or #userId=='4'\"\n" +
            "      },{\n" +
            "        \"name\": \"belongType\",\n" +
            "        \"value\": \"1\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"#belongType=='2'\"\n" +
            "      },{\n" +
            "        \"name\": \"location\",\n" +
            "        \"value\": \"1,2,3\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"#location=='4' or #location=='2' or #location=='3'\"\n" +
            "      }\n" +
            "    ]\n" +
            "  }\n" +
            "]";

/*


    private static final String STRATEGY = "[\n" +
            "  {\n" +
            "    \"name\": \"策略1\",\n" +
            "    \"id\": \"ID1\",\n" +
            "    \"conditions\": [\n" +
            "      {\n" +
            "        \"name\": \"userId\",\n" +
            "        \"value\": \"1,2,3\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"(#userInfo.userId=='1') or (#userInfo.userId=='2')or (#userInfo.userId=='3')\"\n" +
            "      },\n" +
            "      {\n" +
            "        \"name\": \"belongType\",\n" +
            "        \"value\": \"1\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"#userInfo.belongType=='1'\"\n" +
            "      },\n" +
            "      {\n" +
            "        \"name\": \"location\",\n" +
            "        \"value\": \"1,2,3\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"#userInfo.location=='1' or #userInfo.location=='2' or #userInfo.location=='3'\"\n" +
            "      }\n" +
            "    ]\n" +
            "  },\n" +
            "  {\n" +
            "    \"name\": \"策略2\",\n" +
            "    \"id\": \"ID2\",\n" +
            "    \"conditions\": [\n" +
            "      {\n" +
            "        \"name\": \"userId\",\n" +
            "        \"value\": \"2,3\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"#userInfo.userId=='1' or #userInfo.userId=='2' or #userInfo.userId=='3' or #userInfo.userId=='4'\"\n" +
            "      },{\n" +
            "        \"name\": \"belongType\",\n" +
            "        \"value\": \"1\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"#userInfo.belongType=='2'\"\n" +
            "      },{\n" +
            "        \"name\": \"location\",\n" +
            "        \"value\": \"1,2,3\",\n" +
            "        \"operator\": \"=\",\n" +
            "        \"expression\":\"#userInfo.location=='4' or #userInfo.location=='2' or #userInfo.location=='3'\"\n" +
            "      }\n" +
            "    ]\n" +
            "  }\n" +
            "]";
*/


    public static void main(String[] args) {
        AuthenUserInfo authenUserInfo = JSONUtil.toBean(USER, AuthenUserInfo.class);
        List<AuthenStrategy> stgList = JSONUtil.toList(STRATEGY, AuthenStrategy.class);

        StandardEvaluationContext context = new StandardEvaluationContext();
//        context.setVariable("userInfo", userInfo);
        context.setVariables(new JSONObject(authenUserInfo));

        List<AuthenStrategy> matchedStgs = stgList.stream().filter(stg -> {
            String name = stg.getName();
            System.out.println("\n====strategy:" + name);
            List<StrategyCondition> conditions = stg.getConditions();
            return conditions.stream().allMatch(condition -> {
                System.out.println("condition:" + condition.getName() + " value:" + condition.getValue() + " operator:" + condition.getOperator() + " expression:" + condition.getExpression());

                ExpressionParser parser = new SpelExpressionParser();
                Boolean value = parser.parseExpression(condition.getExpression()).getValue(context, boolean.class);
                System.out.println("matched: " + value);
                return value != null && value;
            });
           /* for (StrategyCondition condition : conditions) {
                System.out.println("condition:" + condition.getName() + " value:" + condition.getValue() + " operator:" + condition.getOperator() + " expression:" + condition.getExpression());

                ExpressionParser parser = new SpelExpressionParser();
                Boolean value = parser.parseExpression(condition.getExpression()).getValue(context, boolean.class);
                System.out.println("matched: " + value);
                boolean result = value != null && value;
                if (!result) {
                    return false;
                }
            }
            return true;*/
        }).collect(Collectors.toList());
        System.out.println("匹配到策略：");

        matchedStgs.forEach(s -> System.out.println(s.getName()));

    }
}
